using System.Web;
using System;

using LeastPrivilege.CustomBasicAuthentication.Management;

namespace LeastPrivilege.CustomBasicAuthentication
{
    public partial class CustomBasicAuthenticationModule : IHttpModule
    {
        // event registration
        public void Init(HttpApplication context)
        {
            context.AuthenticateRequest += OnEnter;
            context.EndRequest += OnLeave;
        }

        void OnEnter(object sender, EventArgs e)
        {
            HttpContext context = HttpContext.Current;
            
            // check if module is enabled
            if (!Configuration.Enabled)
                return;

            // check if SSL is required and enabled
            if (Configuration.RequireSSL && !context.Request.IsSecureConnection)
            {
                throw new HttpException(403, "SSL required for Basic Authentication");
            }

            // check if basic authentication header is present
            // if yes - try to authenticate
            // if no - check if anonymous access is allowed
            //         if yes - let authorization decide when authentication is needed
            //         if no  - try to authenticate

            // try to authenticate user - otherwise set status code and end request
            if (IsHeaderPresent)
            {
                if (!AuthenticateUser())
                {
                    DenyAccess();
                }
            }
            else
            {
                // if anonymous requests are not allowed - end the request
                if (!IsAnonymousAllowed)
                {
                    DenyAccess();
                }
            }
        }

        void OnLeave(object sender, EventArgs e)
        {
            // check if module is enabled
            if (Configuration.Enabled)
            {
                if (HttpContext.Current.Response.StatusCode == 401)
                {
                    SendAuthenticationHeader();
                }
            }
        }

        public void Dispose()
        { }
    }
}
